﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Skynet.CommonLibrary.ThreadRefreshTime.Extension;
using Skynet.CommonLibrary.ThreadRefreshTime.Interface;
using Skynet.CommonLibrary.ThreadRefreshTime.StrateGy;

namespace Skynet.CommonLibrary.ThreadRefreshTime.RefreshElement
{
    /// <summary>
    /// 固定周期定时器（1秒执行一次，用来处理未来某一时刻触发的任务）
    /// 条件：只处理设置过开始时间的元素
    /// </summary>
    ///<remarks>
    /// 作者：         李志强
    /// 开发时间：  2011-03-28
    /// </remarks>
    internal  class FixedTimerElement:IRefreshTimer
    {
        //复杂刷新任务列表
        List<IRefreshTaskTimer> _actions = new List<IRefreshTaskTimer>();
        //刷新方式列表,一个刷新任务对应一个刷新方式
        Dictionary<string, IThreadStrategy> _threadSerategy = new Dictionary<string, IThreadStrategy>();

        #region IRefreshTimer 成员

        public string RefreshID
        {
            get;
            set;
        }

        public int RefreshInterval
        {
            get { return 1 * 1000; }
            set { throw new Exception("不允许设置此值。"); }
        }

        public Action<Action<IRefreshTimer, Exception>> Refresh
        {
            get
            {
                return Work;
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public DateTime LastRefreshTime
        {
            get;
            set;
        }



        public DateTime ExecutionTime
        {
            get;
            set;
        }

        public string Description
        {
            get
            {
                return "固定周期定时管理器";
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public void Verify()
        {
            if (string.IsNullOrEmpty(this.RefreshID))
            {
                throw new Exception("编号不能为空");
            }
        }
        #endregion

        /// <summary>
        /// 添加刷新任务到列表
        /// </summary>
        /// <param name="reft"></param>
        /// <param name="serategy"></param>
        public void AddRefreshTimer(IRefreshTaskTimer reft, IThreadStrategy serategy)
        {
            lock (_actions)
            {
                _actions.Add(reft);
                _threadSerategy.Add(reft.RefreshID, serategy);
                //对刷新任务按开始任务时间进行排序,以减少多任务下的循环次数
                _actions = _actions.OrderBy(o => o.TaskStartTime).ToList();
            }
        }

        /// <summary>
        /// 删除刷新任务
        /// </summary>
        /// <param name="reft"></param>
        public void RemoveRefreshTimer(IRefreshTaskTimer reft)
        {
            lock (_actions)
            {
                if (_actions.Contains(reft))
                {
                    _actions.Remove(reft);
                    _threadSerategy.Remove(reft.RefreshID);
                }
            }
        }

        /// <summary>
        /// 要进行的工作,循环需要处理的任务
        /// </summary>
        /// <param name="failed"></param>
        private void Work(Action<IRefreshTimer,Exception> failed)
        {
            if(_actions.Count == 0 )
                return;

            //循环任务列表  查看是否有要开始的任务
            for (int i = 0; i < _actions.Count; i++)
            {
                IRefreshTaskTimer reft = _actions[i] ;
             //判断当前时间是否大于 刷新任务中最小的时间
                if (DateTime.Now >= reft.TaskStartTime)
                {
                    if (!_threadSerategy.ContainsKey(reft.RefreshID))
                    {
                        _actions.Remove(reft);
                        continue; 
                    }

                    IThreadStrategy serategy = _threadSerategy[reft.RefreshID];

                    try
                    {
                        //移除相应元素
                        RemoveRefreshTimer(reft);
                        i--;
                        //如果刷新间隔为0，表示只执行一次
                        if (reft.RefreshInterval == 0)
                        {
                            reft.ExecutiveRefresh(failed, null);
                            failed(reft, new Exception("执行完毕"));
                        }
                        else
                        {
                            serategy.StartWork(
                                () =>
                                {
                                    //记录日志
                                    reft.WriteDebugLog();
                                    //执行相应操作
                                    reft.ExecutiveRefresh(failed, () =>
                                    {
                                        serategy.StopWork();
                                    });
                                },
                                reft.RefreshInterval);
                        }
                    }
                    catch (Exception ex)
                    {
                        if (failed != null)
                        {
                            failed(reft, ex);
                        }
                    }
                }
                else
                {
                    //直接跳出循环
                    break;
                }
            }
            
        }

    }
}
